package com.yunji.base.business;

import com.google.common.collect.Lists;
import com.yunji.base.bo.GetSiteInfoBO;
import com.yunji.base.bo.StaffLocationRemoveBO;
import com.yunji.base.bo.StaffSiteRemoveBO;
import com.yunji.base.cache.BaseCache;
import com.yunji.base.domain.BelongDO;
import com.yunji.base.domain.StaffSiteDO;
import com.yunji.base.dto.StaffDTO;
import com.yunji.base.dto.StaffFiledDTO;
import com.yunji.base.service.*;
import com.yunji.base.vo.StaffVO;
import com.yunji.common.base.BaseBusiness;
import com.yunji.common.enums.common.ErrorEnum;
import com.yunji.common.enums.common.UserType;
import com.yunji.common.model.domain.SiteDO;
import com.yunji.common.model.domain.StaffDO;
import com.yunji.common.model.dto.LoginInfo;
import com.yunji.common.model.enums.LoginTypeEnum;
import com.yunji.common.utils.bean.BeanUtils;
import com.yunji.system.service.TokenService;
import org.springframework.security.crypto.bcrypt.BCrypt;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

/**
 * @Project: yunji-coffee
 * @Package: com.yunji.user.business
 * @Title: StaffBusiness
 * @Description: 员工业务处理
 * History:
 * Date						Version			Author			Summary
 * ========================================================================
 * 2024-04-27 11:58:28		V1.0			HuaAo		新建类
 */
@Component
public class StaffBusiness extends BaseBusiness {
    @Resource
    SiteService siteService;

    @Resource
    StaffService staffService;

    @Resource
    BelongService belongService;

    @Resource
    StaffSiteService staffSiteService;

    @Resource
    StaffLocationService staffLocationService;

    @Resource
    TokenService tokenService;

    private static final String NOT_FOUND_SITE = "未找到网点信息";


    /**
     * @param param 筛选信息
     * @Title search
     * @Desc 查询员工列表信息
     * @Date 2024-06-04 15:07:25.793
     * @Return List<Staff> 员工列表信息
     */
//    public List<Staff> search(StaffParam param) {
//        handleParam(param);
//        return staffService.search(param);
//    }

    /**
     * @param ids 员工ID数组
     * @Title search
     * @Desc 查询员工列表
     * @Date 2024-06-04 19:33:37.514
     * @Return List<Staff> 员工列表
     */
    public List<StaffDO> search(Long... ids) {
        return staffService.listByIds(ids);
    }

    /**
     * @param id 员工ID数组
     * @Title select
     * @Desc 获取员工详情
     * @Date 2024-06-04 19:38:45.395
     * @Return Staff 员工详情
     */
    public StaffDO select(Long id) {
        return staffService.getById(id);
    }

    /**
     * @param dto 员工参数信息
     * @Title checkStaffParam
     * @Desc 校验员工参数信息
     * @Date 2024-06-04 10:09:14.508
     */
    public void checkStaffParam(StaffDTO dto) {
        String name = dto.getStaffName();
        logs.info("【员工信息】员工名称{}", name);
        Assert.isTrue((BeanUtils.isNotNull(name) && name.length() <= 10), "输入的姓名不合法");

        Integer age = dto.getAge();
        logs.info("【员工信息】员工年龄{}", age);
        Assert.isTrue((BeanUtils.isNotNull(age) && age <= 99), "输入的年龄不合法");

        String phone = dto.getStaffId();
        logs.info("【员工信息】员工手机号码{}", phone);
        Assert.isTrue((BeanUtils.isNotNull(phone) && phone.matches("1\\d{10}$")), "输入的手机号码不合法");

        Assert.isTrue(!staffService.existsPhone(dto.getId(), phone), ErrorEnum.BUSINESS_121001.getText());

        Assert.isTrue(BeanUtils.isNotNull(dto.getManageRegion()),"请输入管理区域");
    }

    /**
     * @param staff 员工信息
     * @Title bindStaffSite
     * @Desc 绑定员工网点信息
     * @Date 2024-06-04 10:15:45.286
     */
    public void bindStaffSite(StaffDO staff) {
        StaffSiteDO staffSite = new StaffSiteDO();
        staffSite.setSiteId(staff.getManagerId());
        staffSite.setSiteName(BaseCache.getSiteName(staff.getManagerId()));
        staffSite.setStaffId(staff.getId());
        staffSite.setStaffName(staff.getStaffName());
        staffSite.setStaffTel(staff.getStaffTel());
        staffSite.setBelongId(staff.getBelongId());
        Assert.isTrue(staffSiteService.create(staffSite), "员工站点绑定失败");
    }

    /**
     * @param dto 请求参数
     * @Title create
     * @Desc 创建员工信息
     * @Date 2024-06-04 10:18:11.390
     */
    @Transactional
    public Long create(StaffDTO dto) {
        LoginInfo user = tokenService.getUser();
        Assert.isTrue(BeanUtils.isNotNull(user), "用户无权操作");

        String userType = user.getUserType();
        String userText = UserType.getText(userType);
        logs.info("【新增员工】当前用户类型={}:{}", userType, userText);

        checkStaffParam(dto);

        Long siteId = dto.getSiteId();
        logs.info("【新增员工】上送网点信息:{}", siteId);
        if (BeanUtils.equals(userType, UserType.SITE.getCode())) {
            Long belongId = user.getBelongId();
            logs.info("【新增员工】当前用户所属:{}", belongId);
            BelongDO belong = BaseCache.getBelong(belongId);
            Assert.isTrue(BeanUtils.isNotNull(belong), NOT_FOUND_SITE);
            siteId = belong.getSiteId();
            logs.info("【新增员工】当前网点信息:{}", siteId);
        }

        Assert.isTrue(BeanUtils.isNotNull(siteId), NOT_FOUND_SITE);
        GetSiteInfoBO siteInfoBO = siteService.getSiteInfoBO(siteId);
        BelongDO belong = siteInfoBO.getBelong();
        SiteDO site = siteInfoBO.getSite();

        StaffDO staff = new StaffDO();
        BeanUtils.clone(dto, staff);
        staff.setManagerId(siteId);
        staff.setBelongId(belong.getBelongId());
        staff.setManagerName(site.getSiteName());
        staff.setAgentId(belong.getAgentId());
        staff.setAgentName(siteInfoBO.getAgentName());

        String phone = dto.getStaffId();
        staff.setStaffTel(phone);
        staff.setStaffId(phone);

        String password = phone.substring((phone.length() - 6));
        String salt = BCrypt.gensalt();
        String encrypt = BCrypt.hashpw(password, salt);
        staff.setStaffPwd(encrypt);
        staff.setSalt(salt);

        Assert.isTrue(staffService.create(staff), "创建员工失败");

        bindStaffSite(staff);

        return staff.getId();
    }

    /**
     * @param dto 请求参数
     * @Title update
     * @Desc 更新员工信息
     * @Date 2024-06-04 10:18:36.323
     */
    @Transactional
    public void update(StaffDTO dto) {
        Long id = dto.getId();
        logs.info("【更新员工】员工记录ID{}", id);
        Assert.isTrue(BeanUtils.isNotNull(id), "未找到员工信息");

        // 校验参数信息
        checkStaffParam(dto);

        StaffDO origin = staffService.select(id);
        logs.info("【更新员工】原始员工信息{}", origin);
        Assert.isTrue(BeanUtils.isNotNull(origin), "未找到员工信息");

        // 解除员工绑定网点
        staffSiteService.remove(StaffSiteRemoveBO.builder().staffId(id).build());

        StaffDO staff = new StaffDO();
        BeanUtils.clone(dto, staff);
        staff.setStaffTel(dto.getStaffId());

        Long newSiteId = dto.getSiteId();
        Long rawSiteId = origin.getManagerId();
        logs.info("【更新员工】员工原始网点ID:{},新网点:{}", rawSiteId, newSiteId);

        BelongDO belong = belongService.getBySiteId(UserType.SITE.getCode(), newSiteId);
        staff.setBelongId(belong.getBelongId());

        GetSiteInfoBO siteInfoBO = siteService.getSiteInfoBO(newSiteId);
        Assert.isTrue(BeanUtils.isNotNull(siteInfoBO), NOT_FOUND_SITE);
        if (!BeanUtils.equals(rawSiteId, newSiteId)) {
            deleteStaffToken(staff.getId());
            staffLocationService.delete(StaffLocationRemoveBO.builder().staffIds(Lists.newArrayList(id)).build());
        }
        SiteDO site = siteInfoBO.getSite();
        staff.setManagerId(site.getId());
        staff.setManagerName(site.getSiteName());
        staff.setAgentId(siteInfoBO.getAgentId());
        staff.setAgentName(siteInfoBO.getAgentName());
        Assert.isTrue(staffService.update(staff), "更新员工信息失败");

        bindStaffSite(staff);
    }


    /**
     * @param ids 员工数组
     * @Title delete
     * @Desc 批量员工信息
     * @Date 2024-06-04 18:19:15.930
     */
    @Transactional(rollbackFor = Exception.class)
    public void delete(Long... ids) {
        Assert.isTrue(staffSiteService.deleteByStaffIds(Arrays.asList(ids)), "删除员工站点失败");

        staffLocationService.delete(StaffLocationRemoveBO.builder().staffIds(Arrays.asList(ids)).build());

        Assert.isTrue(staffService.delete(ids), "删除员工失败");

        //删除员工Token
        for (Long id : ids) {
            deleteStaffToken(id);
        }
    }

    /**
     * @param staff 员工信息
     * @Title changeStatus
     * @Desc 变更员工状态
     * @Date 2024-06-04 14:57:07.414
     */
    public void changeStatus(StaffDO staff) {
        Long id = staff.getId();
        logs.info("【员工信息】修改员工{}状态", id);
        Assert.isTrue(BeanUtils.isNotNull(id), "变更状态失败");

        StaffDO update = new StaffDO();
        update.setId(id);
        if (BeanUtils.isNotNull(staff.getStatus())) {
            update.setStatus(staff.getStatus());
        }
        if (BeanUtils.isNotNull(staff.getTestStatus())) {
            update.setTestStatus(staff.getTestStatus());
        }
        deleteStaffToken(id);

        Assert.isTrue(staffService.update(update), "变更状态失败");
    }

    /**
     * @param param 网点ID
     * @Title searchSiteStaff
     * @Desc 查询网点员工列表信息
     * @Date 2024-06-04 15:09:17.707
     * @Return List<Staff> 工列表信息
     */
//    public List<Staff> searchSiteStaff(StaffParam param) {
//        param.setStatus(1);
//        handleParam(param);
//        return staffService.search(param);
//    }

    /**
     * @param param 代理商ID
     * @Title searchAgentStaff
     * @Desc 查询代理商员工列表信息
     * @Date 2024-06-04 15:14:36.085
     * @Return List<Staff> 员工列表信息
     */
//    public List<Staff> searchAgentStaff(StaffParam param) {
//        param.setStatus(1);
//        return staffService.search(param);
//    }

    /**
     * @param staff、员工信息
     * @Title changePassword
     * @Desc 修改员工密码
     * @Date 2024-06-04 15:02:34.586
     */
    public void changePassword(StaffDO staff) {
        Long id = staff.getId();
        logs.info("【员工信息】修改员工{}密码", id);
        Assert.isTrue(BeanUtils.isNotNull(id), "修改密码失败");
        StaffDO update = new StaffDO();

        String password = staff.getStaffPwd();
        String salt = BCrypt.gensalt();
        update.setId(id);
        update.setStaffPwd(BCrypt.hashpw(password, salt));
        update.setSalt(salt);
        Assert.isTrue(staffService.update(update), "修改密码失败");
    }

    /**
     * @return StaffVO
     * @Title current
     * @Intro 获取当前员工用户信息
     * @Date 2024-06-10 22:27:06.580
     */
    public StaffVO selectStaffById(Long id) {
        return staffService.selectStaffById(id);
    }

    /**------------------------------------------ 搜索栏 ------------------------------------------*/

    /**
     * @param name 员工姓名
     * @Title searchName
     * @Desc 搜索员工姓名
     * @Date 2024-09-09 10:19:07.462
     * @Return List<String> 匹配结果
     */
    public List<String> searchName(String name) {
        Assert.isTrue((name.length() <= 6), "输入的员工姓名不合规");
        StaffFiledDTO build = StaffFiledDTO.builder().searchFiled("s.staff_name").staffName(name).build();
        List<String> list = staffService.searchTableField(build);
        return BeanUtils.isNotNull(list) ? list : Collections.emptyList();
    }

    /**
     * @param phone 员工电话
     * @Title searchPhone
     * @Desc 搜索员工电话
     * @Date 2024-09-09 10:19:47.093
     * @Return List<String> 匹配结果
     */
    public List<String> searchPhone(String phone) {
        Assert.isTrue(phone.matches("^\\d{0,11}$"), "输入的员工电话不合规");
        StaffFiledDTO build = StaffFiledDTO.builder().searchFiled("s.staff_tel").staffTel(phone).build();
        List<String> list = staffService.searchTableField(build);
        return BeanUtils.isNotNull(list) ? list : Collections.emptyList();
    }

    /**
     * @param agentName 代理名称
     * @Title searchAgentName
     * @Desc 搜索代理商名称
     * @Date 2024-09-09 10:20:31.444
     * @Return List<String> 匹配结果
     */
    public List<String> searchAgentName(String agentName) {
        Assert.isTrue((agentName.length() <= 15), "输入的代理商名称不合规");
        StaffFiledDTO build = StaffFiledDTO.builder().searchFiled("au.agent_name").agentName(agentName).build();
        List<String> list = staffService.searchTableField(build);
        return BeanUtils.isNotNull(list) ? list : Collections.emptyList();
    }

    /**
     * @param siteName 网点名称
     * @Title searchSiteName
     * @Desc 搜索网点名称
     * @Date 2024-09-09 10:21:08.544
     * @Return List<String> 匹配结果
     */
    public List<String> searchSiteName(String siteName) {
        Assert.isTrue((siteName.length() <= 15), "输入的网点名称不合规");
        StaffFiledDTO build = StaffFiledDTO.builder().searchFiled("ts.site_name").siteName(siteName).build();
        List<String> list = staffService.searchTableField(build);
        return BeanUtils.isNotNull(list) ? list : Collections.emptyList();
    }

    /**
     * @Title deleteStaffToken
     * @Desc 删除员工token
     * @Date 2024-10-24 15:35:12.090
     */
    public void deleteStaffToken(Long id) {
        redisCache.delete(TokenService.getTokenKey(LoginTypeEnum.STAFF, id));
    }
}